package when3meet.controller;

import java.util.ArrayList;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import when3meet.model.ClientInfo;
import when3meet.model.Edge;
import when3meet.view.DecisionLinePanel;
import when3meet.view.MainFrame;
import xml.Message;

/**
 * Handle turn response, expand the number of allowed edge by 1, when the event
 * is completed, draw the result
 * 
 * @author Xi
 * 
 */
public class TurnResponseController {

	ArrayList<Integer> x = new ArrayList<Integer>();
	ArrayList<Integer> y = new ArrayList<Integer>();

	public void process(Message response) {

		Node update = response.contents.getFirstChild();
		NamedNodeMap map = update.getAttributes();

		String completed = "";
		try {
			completed = map.getNamedItem("completed").getNodeValue();
		} catch (java.lang.NullPointerException e) {

		}
		// only thing to do is expand allowed edges' size by one
		if (completed.equals("false")) {
			MainFrame frame = MainFrame.getInstance();

			int size = frame.getDecisionLineZone().getCurrentAllowedEdge();
			frame.getDecisionLineZone().setCurrentAllowedEdge(size + 1);
			frame.getAddEdgeButton().setEnabled(true);
		}

		// return result to user if the event is completed
		if (completed.contains("true")) {

			MainFrame.getInstance().getAddEdgeButton().setEnabled(false);
			// TODO should I calculate the number of edges, so I know when the
			// event
			// will complete, or just let server do this for me :)
			getResult();
		}

	}

	/**
	 * return result for the event.
	 */
	private void getResult() {

		x.add(19);
		y.add(521);
		// recursively find point belong to best choice. The best choice is the
		// one which terminates at first choice, so we do a track back from
		// first choice, at last will find the best choice
		addPoint(19, 521);

		DecisionLinePanel.getInstance(0, null).setPolyLine(x.toArray(new Integer[x.size()]),
				y.toArray(new Integer[y.size()]));

	}

	/**
	 * recursively find point belong to best choice path, the parameter point is
	 * the current start point from best choice path, the next point would have
	 * the same x position with current point and its y position is closest to
	 * current point, if no such point exists, means we find the best choice
	 * 
	 * @param x
	 * @param y
	 */
	void addPoint(int x, int y) {
		Edge[] edges = ClientInfo.getInstance().getEdges();
		int closestPoint = -1;
		int width = DecisionLinePanel.getInstance(0, null).getCurrentWidth();
		// judge which direction we find the closest edge, true- if in right;
		// false- if in left
		boolean flag = true;

		for (int i = 0; i < edges.length; i++) {
			if (edges[i].left == x && edges[i].height < y) {
				if (closestPoint < 0)
					closestPoint = edges[i].height;
				else if (edges[i].height > closestPoint)
					closestPoint = edges[i].height;
			}
		}

		for (int i = 0; i < edges.length; i++) {
			if (edges[i].left + width == x && edges[i].height < y) {
				if (closestPoint < 0) {
					closestPoint = edges[i].height;
					flag = false;
				} else if (edges[i].height > closestPoint) {
					closestPoint = edges[i].height;
					flag = false;
				}
			}
		}

		if (closestPoint < 0) {
			// termination
			this.x.add(x);
			this.y.add(30);

		} else {
			// judge in which direction we find the optimal edge
			if (flag == true) {
				this.x.add(x);
				this.y.add(closestPoint);
				this.x.add(x + width);
				this.y.add(closestPoint);
				addPoint(x + width, closestPoint);
			} else if (flag == false) {
				this.x.add(x);
				this.y.add(closestPoint);
				this.x.add(x - width);
				this.y.add(closestPoint);
				flag = true;
				addPoint(x - width, closestPoint);
			}
		}
	}
}
